#include <fstream>
#include <stack>
#include <typeinfo>
#include <bitset>
#include <iostream>
#include <map>
#ifdef _WIN32
#include "windows.h"
#endif
#include "stdio.h"
//#pragma warning(disable:4996)
#include "util/frame_manager.h"
#include "util/utiltool.h"
#include "common/container/details/fixed_buffer.h"
#include "util/util.h"
//#include "test/test.h"
#include "common/os/time.h"
#include "common/os/file.h"
#include <stdarg.h>
#include <unordered_map>
#include <string>
#include "helper/file_helper.h"
#include "thread/loop_thread.h"
#ifndef _WIN32
#include "redis/redis_client.h"
#endif
#include <memory>
#include "proxy/proxy.h"
#include <cassert>
//#include "hasio/include/detail/scheduler.hpp"
//#include "hasio/include/io_context.hpp"
//#include "hasio/include/basic_socket.hpp"
//#include "hasio/include/ip/tcp.hpp"

//static Test::TestC tc;
//#define Log(tag,format,...) tc.test_log_tag_fmt(tag,format,##__VA_ARGS__)
//#define LogAction(format,...) Log(Test::TestC::LogTagAction(), format, ##__VA_ARGS__)

char log_buffer_[100];
bool warn(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    vsprintf(log_buffer_, fmt, ap);
    va_end(ap);
    printf("%s \n", log_buffer_);
    return true;
}

#include <errno.h>
using error_code = std::error_code;

namespace test {
namespace error {

enum class basic_errors : uint8_t
{
    bad_descriptor = 1,
    bad_name = 2,
};

inline error_code make_error_code(basic_errors e)
{
  return error_code(
      static_cast<int>(e), std::system_category());
}

}
}


namespace std {

template<> struct is_error_code_enum<test::error::basic_errors> : true_type {};

}

class BaseClass {
public:
    virtual char* name() const = 0;
};

class SubClass : public BaseClass {
public:
    virtual char* name() const override
    {
        return "hello";
    }
};

class TestCallback {
public:
    TestCallback() = default;
    TestCallback(int* msg) {
        msg_ = msg;
    }
    ~TestCallback() {
        std::cout << "destuct" << '\n';
      if (msg_) {
        std::cout << "delete " << msg_ << " " << *msg_ << '\n';
        delete msg_;
      }
      msg_ = nullptr;
    }
    TestCallback(TestCallback &&rhs) {
        std::cout << "move construct" << '\n';
        *this = std::forward<TestCallback>(rhs);
    }
    TestCallback(const TestCallback &rhs) = delete;
    // TestCallback(const TestCallback &rhs) {
    //     std::cout << "normal construct" << '\n';
    //     *this = rhs;
    // }
    TestCallback& operator = (const TestCallback &rhs) = delete;
    // TestCallback& operator = (const TestCallback &rhs) {
    //     std::cout << "copy op" << '\n';
    //     if (this != &rhs) {
    //       if (this->msg_ != nullptr) {
    //           delete this->msg_;
    //           this->msg_ = nullptr;
    //       }
    //       this->msg_ = new int(*this->msg_);
    //     }
    //     return *this;
    // }
    TestCallback& operator = (TestCallback &&rhs) {
        std::cout << "move op" << '\n';
        msg_ = rhs.msg_;
        rhs.msg_ = nullptr;
        return *this;
    }

    // int* msg_{nullptr};
    int* msg_;
};

void transfer(TestCallback &&cb) {
    std::cout << "msg:" << cb.msg_ << " " << *cb.msg_ << '\n';
    std::vector<TestCallback> cb_list;
    cb_list.emplace_back(std::forward<TestCallback>(cb));
}

struct TD {
    std::string name;
    int iv;
    float fv;
    char cv;
    std::map<int, std::string> dic;
    char song[10];
};

class CA {
public:
    CA() = default;
    CA(const CA&) = default;
    CA& operator=(const CA&) = default;
    std::string name;
    int iv;
    float fv;
    char cv;
    std::map<int, std::string> dic;
    TD data;
};

class CB {
public:
    int iv;
    float fv;
    char cv;
    std::string name;
};

int main(int argc, char *argv[])
{
    SubClass s;
    const BaseClass &b = *(&s);
    std::cout << "name:" << b.name() << '\n';

    error_code ec;
    ec = test::error::basic_errors::bad_descriptor;
    std::cout << "ec.value:" << ec.value() << '\n';
    std::cout << "ec.name:" << ec.category().name() << '\n';
    std::cout << "ec.message:" << ec.category().message(ec.value()) << '\n';

    TestCallback cb(new int(10));
    // TestCallback cb2;
    // auto cb2 = cb;
    transfer(std::move(cb));
    // transfer(std::move(cb2));

    return 0;
    auto proxy_ptr = std::dynamic_pointer_cast<Proxy>(std::make_shared<GuildServiceBasicProxyImpl>());
    assert(proxy_ptr);
    auto proxy_impl_ptr = std::dynamic_pointer_cast<ProxyImpl>(proxy_ptr);
    assert(proxy_impl_ptr);
    std::cout << proxy_ptr->isConnected() << '\n';
    return 0;

	CA* ca = new CA();
    assert(ca);
    ca->name = "nameCA";
    ca->iv = 100;
    ca->fv = 3.14;
    ca->cv = 'c';
    ca->dic[1] = "C++";
    ca->dic[2] = "Go";

    ca->data.name = "nameTD";
    ca->data.iv = 100;
    ca->data.fv = 3.14;
    ca->data.cv = 'c';
    ca->data.dic[1] = "C";
    ca->data.song[0] = 'H';
    ca->data.song[1] = 'J';
    ca->data.song[2] = 'W';
    ca->data.song[3] = '\0';
    
    // CA* cb = new CA(*ca);
    // assert(cb);

    // printf("cb.name:%s cb.iv:%d cb.fv:%.2f cb.cv:%c cb.dic1:%s\n",
    //        cb->name.c_str(), cb->iv, cb->fv, cb->cv, cb->dic[1].c_str());
    // printf("cd.name:%s cd.iv:%d cd.fv:%.2f cd.cv:%c cd.dic1:%s cd.song:%s\n",
    //        cb->data.name.c_str(), cb->data.iv, cb->data.fv, cb->data.cv,
    //        cb->data.dic[1].c_str(), cb->data.song);
    
    CB *c3 = new CB();
    printf("c3.iv:%d c3.fv:%.2f c3.cv:%c\n", c3->iv, c3->fv, c3->cv);
    {
        std::string s("hello world");
    }
    CB c4;
    printf("c4.name:%s c4.iv:%d c4.fv:%.2f c4.cv:%c\n", c4.name.c_str(), c4.iv, c4.fv, c4.cv);



    return 0;
    // auto proxy_ptr = std::dynamic_pointer_cast<Proxy>(std::make_shared<GuildServiceBasicProxyImpl>());
    // assert(proxy_ptr);
    // auto proxy_impl_ptr = std::dynamic_pointer_cast<ProxyImpl>(proxy_ptr);
    // assert(proxy_impl_ptr);
    // std::cout << proxy_ptr->isConnected() << '\n';
    // return 0;
    // timeval timeval;
    // os::gettimeofday(&timeval, nullptr);
    // printf("gettimeofday sec:%d usec:%d\n", timeval.tv_sec, timeval.tv_usec);
    // return 0;

    loop_thread loop_th;
    auto* loop = loop_th.start_loop();

    std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    loop_th.stop_loop();

    loop = loop_th.start_loop();

    std::this_thread::sleep_for(std::chrono::milliseconds(2000));

    return 0;
}